`timescale 1ns / 1ps

module decoder (
	input  wire [31:0] ir,
	output wire [4:0] rs,
	output reg  require_rs,
	output wire [4:0] rt,
	output reg  require_rt,
	output reg  [4:0] wd,
	output reg  reg_write,
	output wire [31:0] imm,
	output reg  [5:0] alu_op,
	output wire [4:0] shamt
);

	assign rs = ir[25:21];
	assign rt = ir[20:16];

	assign shamt = ir[10:6];
	
	assign imm = (ir[31:27] == 5'b00001) ? 0 : {{16 {ir[15]}}, ir[15:0]};
	
	
	reg [1:0] RegWtDst;
	
	always @* begin 
		case (ir[31:26])
			// R Type
			6'b000000: begin 
				alu_op = ir[5:0];
				RegWtDst = 2'b01;
				reg_write = 1'b1;
				require_rs = 1;
				require_rt = 1;
			end
			
			// I Type
			6'b001000, 6'b001001, 6'b001100, 6'b001101, 6'b001110, 6'b001111, 6'b001010, 6'b001011: begin
				alu_op = ir[31:26];
				RegWtDst = 2'b00;
				reg_write = 1'b1;
				require_rs = 1;
				require_rt = 0;
			end
			
			// lw
			6'b100011: begin
				alu_op = 6'b100000;
				RegWtDst = 2'b00;
				reg_write = 1'b1;
				require_rs = 1;
				require_rt = 0;
			end
			
			// sw
			6'b101011: begin
				alu_op = 6'b100000;
				RegWtDst = 2'b00;
				reg_write = 1'b0;
				require_rs = 1;
				require_rt = 1;
			end
			
			// beq, bne
			6'b000100, 6'b000101: begin
				alu_op = 6'b100000;
				RegWtDst = 2'b00;
				reg_write = 1'b0;
				require_rs = 1;
				require_rt = 1;
			end
			
			// j
			6'b000010: begin
				alu_op = 6'b100000;
				RegWtDst = 2'b00;
				reg_write = 1'b0;
				require_rs = 0;
				require_rt = 0;
			end 
			
			// jal
			6'b000011: begin
				alu_op = 6'b100000;
				RegWtDst = 2'b11;
				reg_write = 1'b1;
				require_rs = 0;
				require_rt = 0;
			end

			default: begin
				alu_op = 6'b000000;
				RegWtDst = 2'b00;
				reg_write = 1'b0;
				require_rs = 0;
				require_rt = 0;
			end

		endcase 
	
		case (RegWtDst) 
			2'b00: wd = ir[20:16];
			2'b01: wd = ir[15:11];
			2'b10: wd = 5'b11111;
			2'b11: wd = 5'b11111;
		endcase
	end 


endmodule  
